import datetime
import os
import urllib

from google.appengine.api import urlfetch
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.runtime.apiproxy_errors import CapabilityDisabledError


class SVN_Repo(db.Model):
  master = db.BooleanProperty(required=True)
  url = db.LinkProperty(required=True)
  UUID = db.StringProperty(required=True)
  revision = db.IntegerProperty()
  last_checked = db.DateTimeProperty(auto_now=True, auto_now_add=True)


class SVN_Mirrors(webapp.RequestHandler):
  def get(self):
    if self.request.get('check') == 'true':
      # get URL of MASTER repository
      repos = db.GqlQuery("SELECT * FROM SVN_Repo WHERE master=True LIMIT 1")
      
      if repos.count() == 0:
        add_mirror() # add default SVN mirrors
        repos = db.GqlQuery("SELECT * FROM SVN_Repo WHERE master=True LIMIT 1")
      
      for master in repos:
        # always...
          # check/update MASTER revision
          master.revision = remote_svn_revision(master.url)
          master.UUID = remote_svn_UUID(master.url)
          if master.revision > 0 and master.UUID != "failed-to-check-UUID":
            try:
              master.put()
            except CapabilityDisabledError:
              readonly = True
      
      # get URL of MIRROR repositories
      repos = db.GqlQuery("SELECT * FROM SVN_Repo WHERE master=False")
      for r in repos:
        if r.revision < master.revision or (r.UUID != master.UUID and master.UUID != "failed-to-check-UUID"):
          # update mirror (we wish) ^_^
          
          # check/update MIRROR revision
          r.revision = remote_svn_revision(r.url)
          r.UUID = remote_svn_UUID(r.url)
          if r.revision > 0 and r.UUID != "failed-to-check-UUID":
            try:
              r.put()
            except CapabilityDisabledError:
              readonly = True
      
    else:
      # self.response.headers["Content-Type"] = "text/plain"
      self.response.out.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" /> 
""")
      # automatic page refreshing
      if self.request.get('refresh') == 'on':
        self.response.out.write("""<meta http-equiv="refresh" content="300;url=%s://%s%s?%s" />""" % 
                               ('https' if os.environ['SERVER_PORT']=='443' else 'http', 
                                os.environ['HTTP_HOST'],
                                os.environ['PATH_INFO'],
                                os.environ['QUERY_STRING'])
                               )
      self.response.out.write("""
<title>SVN Mirrors</title>
<style type="text/css">body {
	font-family: Arial, Helvetica, sans-serif;
}
</style>

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-16687257-7']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
</script>

</head>

<body>
<h2><a href="http://rathena.org/board/index.php?showannouncement=5&amp;f=0" target="_top">rAthena Forums > SVN Mirrors</a></h2>

<table>
<tr><td>revision</td><td>last checked</td><td>url</td><td>UUID</td></tr>
""")
      
      # get info of MASTER repository
      repos = db.GqlQuery("SELECT * FROM SVN_Repo WHERE master=True LIMIT 1")
      for master in repos:
        self.response.out.write("<tr><td><font color=\"#00BB00\"><b>%d</b></font></td><td>%s</td><td><b><a href=\"%s\" target=\"_blank\">%s</a></b></td><td>%s</td></tr>\n"
                                % (master.revision, master.last_checked.strftime("%Y-%m-%d %H:%M:%S"), master.url, master.url, master.UUID))
      
      # get info of MIRROR repositories
      repos = db.GqlQuery("SELECT * FROM SVN_Repo WHERE master=False ORDER BY revision DESC, last_checked ASC")
      for r in repos:
        self.response.out.write("<tr><td><font color=\"%s\">%d</font></td><td>%s</td><td><a href=\"%s\" target=\"_blank\">%s</a></td><td><font color=\"%s\">%s</font></td></tr>\n"
                                % ("#00BB00" if r.revision == master.revision else "#FF0000", r.revision, 
                                   r.last_checked.strftime("%Y-%m-%d %H:%M:%S"), r.url, r.url, 
                                   "#000000" if r.UUID == master.UUID else "#FF0000", r.UUID)
                               )
      
      
      self.response.out.write("""</table>

<br />
<i>Last updated on %s (%s)</i><br />
<address style="text-align: right;"><a href="http://code.google.com/appengine/" target="_blank"><img src="%s://code.google.com/appengine/images/appengine-noborder-120x30.gif" alt="Powered by Google App Engine" border="0" /></a></address>
</body>
</html>
""" % (master.last_checked.strftime("%a %B %d, %Y - %I:%M %p"), os.environ['TZ'], 'https' if os.environ['SERVER_PORT']=='443' else 'http'))
    


def remote_svn_revision(url = None):
  revision = 0
  try:
    result = urlfetch.fetch(url, headers = {'Cache-Control' : 'max-age=60'})
  except urlfetch.DownloadError:
    revision = -1
  else:
    if result.status_code == 200:
      head = result.content
      head = head.split('- Revision ', 2)
      head = head[1].split(':', 2)
      revision = int(head[0])
  return revision

def remote_svn_UUID(url = None):
  UUID = "unknown"
  try:
    result = urlfetch.fetch('https://host385.hostmonster.com/~sylvyrco/ea/status/remote_svn_UUID.php?url=%s' % urllib.quote_plus(url), headers = {'Cache-Control' : 'max-age=60'})
  except urlfetch.DownloadError:
    UUID = "failed-to-check-UUID"
  else:
    if result.status_code == 200:
      if result.content != "":
        UUID = result.content
  return UUID

def add_mirror():
  repo = SVN_Repo(master = True,
                  url = db.Link('http://svn.code.sf.net/p/rathena/svn/'),
                  UUID = '54d463be-8e91-2dee-dedb-b68131a5f0ec')
  repo.put()
  repo = SVN_Repo(master = False,
                  url = db.Link('https://rathena.svn.sourceforge.net/svnroot/rathena/'),
                  UUID = 'unknown')
  repo.put()
  repo = SVN_Repo(master = False,
                  url = db.Link('http://svn.rathena.org/svn/rathena/'),
                  UUID = 'unknown')
  repo.put()
  repo = SVN_Repo(master = False,
                  url = db.Link('http://rathena.googlecode.com/svn/'),
                  UUID = 'unknown')
  repo.put()
  return


application = webapp.WSGIApplication([
  ('/tools/svn-status\.py', SVN_Mirrors),
], debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()
